package com.edison.demo.biz;

import com.edison.demo.dto.BatchDataGenerateDTO;
import com.edison.demo.service.DataBatchService;
import com.edison.demo.service.DataGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @author edison
 */
@Component
@Slf4j
public class DataBatchManager {

    private final DataBatchService dataBatchService;
    @Autowired
    public DataBatchManager(DataBatchService dataBatchService) {
        this.dataBatchService = dataBatchService;
    }


    private static final int DEFAULT_DATE_SIZE = 10 * 1000 * 100;

    private static final int DEFAULT_BATCH_SIZE = 10 * 1000;



    public CompletableFuture<Integer> generateConsumerBaseInfo(BatchDataGenerateDTO batchDataGenerateDTO) throws ExecutionException, InterruptedException {
        initBatchDataGenerateDTO(batchDataGenerateDTO);
        return generateData(batchDataGenerateDTO.getDataSize(),batchDataGenerateDTO.getBatchSize(),dataBatchService::generateConsumerBaseInfo);
    }

    public CompletableFuture<Integer> generateCustomerPersonalBasicInfo(BatchDataGenerateDTO batchDataGenerateDTO) throws ExecutionException, InterruptedException {
        initBatchDataGenerateDTO(batchDataGenerateDTO);
        return generateData(batchDataGenerateDTO.getDataSize(),batchDataGenerateDTO.getBatchSize(),dataBatchService::generateCustomerPersonalBasicInfo);
    }
    private void initBatchDataGenerateDTO(BatchDataGenerateDTO batchDataGenerateDTO) {
        if (batchDataGenerateDTO.getDataSize() <= 0) {
            batchDataGenerateDTO.setDataSize(DEFAULT_DATE_SIZE);
        }
        if (batchDataGenerateDTO.getBatchSize() <=0) {
            batchDataGenerateDTO.setBatchSize(DEFAULT_BATCH_SIZE);
        }
    }


    public CompletableFuture<Integer> generateData(int dataSize,int batchSize, DataGenerator dataGenerator) throws ExecutionException, InterruptedException {
        log.info("begin to generate data, total items: {}", dataSize);
        // Split data batch
        List<CompletableFuture<Integer>> updatedFutures = new ArrayList<>();
        log.info("Data generating ....");
        int updated = 0;
        int fullBatches = dataSize / batchSize + 1;

        for (int i = 0; i < fullBatches; i++) {
            if (i == fullBatches - 1) {
                updatedFutures.add(dataGenerator.generate(dataSize % batchSize));
                break;
            }
            updatedFutures.add(dataGenerator.generate(batchSize));
            CompletableFuture.allOf(updatedFutures.toArray(new CompletableFuture[0])).join();
        }
        for (CompletableFuture<Integer> future : updatedFutures) {
            updated += future.get();
        }

        return CompletableFuture.completedFuture(updated);
    }

}
